/**
 * @file drv_flash.c
 * @brief 通用Flash读写驱动实现文件
 * @author Claude Code
 * @date 2025-08-09
 * @note 纯驱动层，不包含业务逻辑，基于STM32 HAL库
 */

#include "drv_flash.h"
#include <string.h>

/* ================= 私有宏定义 ================= */

/** @brief 默认CRC16多项式 */
#define DRV_FLASH_DEFAULT_CRC_POLY      0x1021

/** @brief Flash操作超时时间(ms) */
#define DRV_FLASH_TIMEOUT_MS            5000

/* ================= 私有变量 ================= */

/** @brief 驱动初始化标志 */
static bool s_drv_flash_initialized = false;

/* ================= 私有函数声明 ================= */

/**
 * @brief 计算CRC16校验值
 * @param data 数据指针
 * @param size 数据大小
 * @param poly CRC多项式
 * @retval CRC16校验值
 */
static uint16_t calculate_crc16_internal(const uint8_t* data, uint32_t size, uint16_t poly);

/**
 * @brief 检查地址是否对齐
 * @param addr 地址
 * @param alignment 对齐字节数
 * @retval true 已对齐
 * @retval false 未对齐
 */
static bool is_address_aligned(uint32_t addr, uint32_t alignment);

/* ================= 公共函数实现 ================= */

/**
 * @brief 初始化Flash驱动
 */
drv_flash_status_t drv_flash_init(void)
{
    s_drv_flash_initialized = true;
    return DRV_FLASH_OK;
}

/**
 * @brief 擦除Flash页
 */
drv_flash_status_t drv_flash_erase_pages(uint32_t page_addr, uint32_t page_count)
{
    if (!s_drv_flash_initialized || page_count == 0) {
        return DRV_FLASH_ERROR_PARAM;
    }
    
    // 检查页对齐
    if (!is_address_aligned(page_addr, DRV_FLASH_PAGE_SIZE)) {
        return DRV_FLASH_ERROR_PARAM;
    }
    
    HAL_StatusTypeDef hal_status;
    uint32_t page_error = 0;
    
    // 解锁Flash
    hal_status = HAL_FLASH_Unlock();
    if (hal_status != HAL_OK) {
        return DRV_FLASH_ERROR_UNLOCK;
    }
    
    // 配置擦除结构
    FLASH_EraseInitTypeDef erase_init;
    erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
    erase_init.PageAddress = page_addr;
    erase_init.NbPages = page_count;
    
    // 执行擦除
    hal_status = HAL_FLASHEx_Erase(&erase_init, &page_error);
    
    // 锁定Flash
    HAL_FLASH_Lock();
    
    if (hal_status != HAL_OK) {
        return DRV_FLASH_ERROR_ERASE;
    }
    
    return DRV_FLASH_OK;
}

/**
 * @brief 写入数据到Flash
 */
drv_flash_status_t drv_flash_write(uint32_t addr, const void* data, uint32_t size)
{
    if (!s_drv_flash_initialized || !data || size == 0) {
        return DRV_FLASH_ERROR_PARAM;
    }
    
    HAL_StatusTypeDef hal_status;
    const uint8_t* src = (const uint8_t*)data;
    uint32_t write_addr = addr;
    uint32_t bytes_written = 0;
    
    // 解锁Flash
    hal_status = HAL_FLASH_Unlock();
    if (hal_status != HAL_OK) {
        return DRV_FLASH_ERROR_UNLOCK;
    }
    
    // 根据编程类型进行写入
#if (DRV_FLASH_TYPEPROGRAM == FLASH_TYPEPROGRAM_HALFWORD)
    // 半字编程 - 需要2字节对齐
    uint16_t temp_halfword;
    
    // 处理未对齐的第一个字节
    if (!is_address_aligned(write_addr, 2) && bytes_written < size) {
        // 读取当前半字，修改低字节
        temp_halfword = drv_flash_read_halfword(write_addr & ~0x1);
        temp_halfword = (temp_halfword & 0xFF00) | src[bytes_written];
        
        hal_status = HAL_FLASH_Program(DRV_FLASH_TYPEPROGRAM, write_addr & ~0x1, temp_halfword);
        if (hal_status != HAL_OK) {
            HAL_FLASH_Lock();
            return DRV_FLASH_ERROR_PROGRAM;
        }
        
        write_addr++;
        bytes_written++;
    }
    
    // 写入完整的半字
    while (bytes_written + 1 < size) {
        temp_halfword = (uint16_t)src[bytes_written] | ((uint16_t)src[bytes_written + 1] << 8);
        
        hal_status = HAL_FLASH_Program(DRV_FLASH_TYPEPROGRAM, write_addr, temp_halfword);
        if (hal_status != HAL_OK) {
            HAL_FLASH_Lock();
            return DRV_FLASH_ERROR_PROGRAM;
        }
        
        write_addr += 2;
        bytes_written += 2;
    }
    
    // 处理最后的奇数字节
    if (bytes_written < size) {
        // 读取当前半字，修改高字节
        temp_halfword = drv_flash_read_halfword(write_addr);
        temp_halfword = (temp_halfword & 0x00FF) | ((uint16_t)src[bytes_written] << 8);
        
        hal_status = HAL_FLASH_Program(DRV_FLASH_TYPEPROGRAM, write_addr, temp_halfword);
        if (hal_status != HAL_OK) {
            HAL_FLASH_Lock();
            return DRV_FLASH_ERROR_PROGRAM;
        }
    }
    
#elif (DRV_FLASH_TYPEPROGRAM == FLASH_TYPEPROGRAM_WORD)
    // 字编程 - 需要4字节对齐
    uint32_t temp_word;
    
    // 简化实现，仅支持字对齐的写入
    if (!is_address_aligned(write_addr, 4)) {
        HAL_FLASH_Lock();
        return DRV_FLASH_ERROR_PARAM;
    }
    
    while (bytes_written + 3 < size) {
        temp_word = ((uint32_t)src[bytes_written]) |
                   ((uint32_t)src[bytes_written + 1] << 8) |
                   ((uint32_t)src[bytes_written + 2] << 16) |
                   ((uint32_t)src[bytes_written + 3] << 24);
        
        hal_status = HAL_FLASH_Program(DRV_FLASH_TYPEPROGRAM, write_addr, temp_word);
        if (hal_status != HAL_OK) {
            HAL_FLASH_Lock();
            return DRV_FLASH_ERROR_PROGRAM;
        }
        
        write_addr += 4;
        bytes_written += 4;
    }
    
    // 处理剩余字节
    if (bytes_written < size) {
        temp_word = 0xFFFFFFFF; // Flash擦除后的默认值
        for (uint32_t i = 0; i < (size - bytes_written); i++) {
            temp_word &= ~(0xFF << (i * 8));
            temp_word |= ((uint32_t)src[bytes_written + i]) << (i * 8);
        }
        
        hal_status = HAL_FLASH_Program(DRV_FLASH_TYPEPROGRAM, write_addr, temp_word);
        if (hal_status != HAL_OK) {
            HAL_FLASH_Lock();
            return DRV_FLASH_ERROR_PROGRAM;
        }
    }
#endif
    
    // 锁定Flash
    HAL_FLASH_Lock();
    
    return DRV_FLASH_OK;
}

/**
 * @brief 从Flash读取数据
 */
drv_flash_status_t drv_flash_read(uint32_t addr, void* data, uint32_t size)
{
    if (!s_drv_flash_initialized || !data || size == 0) {
        return DRV_FLASH_ERROR_PARAM;
    }
    
    memcpy(data, (const void*)addr, size);
    return DRV_FLASH_OK;
}

/**
 * @brief 写入单个字节
 */
drv_flash_status_t drv_flash_write_byte(uint32_t addr, uint8_t data)
{
    return drv_flash_write(addr, &data, 1);
}

/**
 * @brief 写入半字(16位)
 */
drv_flash_status_t drv_flash_write_halfword(uint32_t addr, uint16_t data)
{
    if (!is_address_aligned(addr, 2)) {
        return DRV_FLASH_ERROR_PARAM;
    }
    
    HAL_StatusTypeDef hal_status;
    
    hal_status = HAL_FLASH_Unlock();
    if (hal_status != HAL_OK) {
        return DRV_FLASH_ERROR_UNLOCK;
    }
    
    hal_status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, addr, data);
    
    HAL_FLASH_Lock();
    
    if (hal_status != HAL_OK) {
        return DRV_FLASH_ERROR_PROGRAM;
    }
    
    return DRV_FLASH_OK;
}

/**
 * @brief 写入字(32位)
 */
drv_flash_status_t drv_flash_write_word(uint32_t addr, uint32_t data)
{
    if (!is_address_aligned(addr, 4)) {
        return DRV_FLASH_ERROR_PARAM;
    }
    
#if defined(FLASH_TYPEPROGRAM_WORD)
    HAL_StatusTypeDef hal_status;
    
    hal_status = HAL_FLASH_Unlock();
    if (hal_status != HAL_OK) {
        return DRV_FLASH_ERROR_UNLOCK;
    }
    
    hal_status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr, data);
    
    HAL_FLASH_Lock();
    
    if (hal_status != HAL_OK) {
        return DRV_FLASH_ERROR_PROGRAM;
    }
    
    return DRV_FLASH_OK;
#else
    // 使用两个半字写入
    drv_flash_status_t status;
    
    status = drv_flash_write_halfword(addr, (uint16_t)(data & 0xFFFF));
    if (status != DRV_FLASH_OK) {
        return status;
    }
    
    status = drv_flash_write_halfword(addr + 2, (uint16_t)(data >> 16));
    return status;
#endif
}

/**
 * @brief 读取单个字节
 */
uint8_t drv_flash_read_byte(uint32_t addr)
{
    return *(volatile uint8_t*)addr;
}

/**
 * @brief 读取半字(16位)
 */
uint16_t drv_flash_read_halfword(uint32_t addr)
{
    return *(volatile uint16_t*)addr;
}

/**
 * @brief 读取字(32位)
 */
uint32_t drv_flash_read_word(uint32_t addr)
{
    return *(volatile uint32_t*)addr;
}

/**
 * @brief 检查Flash页是否已擦除
 */
bool drv_flash_is_page_erased(uint32_t page_addr)
{
    if (!is_address_aligned(page_addr, DRV_FLASH_PAGE_SIZE)) {
        return false;
    }
    
    const uint32_t* ptr = (const uint32_t*)page_addr;
    uint32_t word_count = DRV_FLASH_PAGE_SIZE / sizeof(uint32_t);
    
    for (uint32_t i = 0; i < word_count; i++) {
        if (ptr[i] != 0xFFFFFFFF) {
            return false;
        }
    }
    
    return true;
}

/**
 * @brief 获取页大小
 */
uint32_t drv_flash_get_page_size(void)
{
    return DRV_FLASH_PAGE_SIZE;
}

/**
 * @brief 获取页起始地址
 */
uint32_t drv_flash_get_page_addr(uint32_t addr)
{
    return (addr / DRV_FLASH_PAGE_SIZE) * DRV_FLASH_PAGE_SIZE;
}

/**
 * @brief 计算CRC16校验值
 */
uint16_t drv_flash_calc_crc16(const void* data, uint32_t size, uint16_t poly)
{
    if (!data || size == 0) {
        return 0;
    }
    
    uint16_t crc_poly = (poly == 0) ? DRV_FLASH_DEFAULT_CRC_POLY : poly;
    return calculate_crc16_internal((const uint8_t*)data, size, crc_poly);
}

/* ================= 私有函数实现 ================= */

/**
 * @brief 计算CRC16校验值
 */
static uint16_t calculate_crc16_internal(const uint8_t* data, uint32_t size, uint16_t poly)
{
    uint16_t crc = 0xFFFF;
    
    for (uint32_t i = 0; i < size; i++) {
        crc ^= (uint16_t)data[i] << 8;
        
        for (uint8_t j = 0; j < 8; j++) {
            if (crc & 0x8000) {
                crc = (crc << 1) ^ poly;
            } else {
                crc <<= 1;
            }
        }
    }
    
    return crc;
}

/**
 * @brief 检查地址是否对齐
 */
static bool is_address_aligned(uint32_t addr, uint32_t alignment)
{
    return (addr % alignment) == 0;
}
